/* Recursive File Lister
   Version 2
   By DreamVB
*/

#include <iostream>
#include <Windows.h>
using namespace std;
using std::cout;
using std::endl;

string LCase(const string& src)
{
	string dest(src);

	for (char& ch : dest)
		ch = tolower(ch);

	return dest;
}

string FixPath(string src){
	if (src[src.length() - 1] != '\\'){
		return src + "\\";
	}
	return src;
}

bool DirExists(string filename){
	if ((GetFileAttributesA(filename.c_str()) != FILE_ATTRIBUTE_DIRECTORY)){
		return false;
	}
	return true;
}

void DirTree(string Path, string FileType, bool AllDirs){
	HANDLE f = 0;
	WIN32_FIND_DATAA wfd;

	string lzPath = "";
	string NewPath = "";
	string fExt = "";
	int pos = string::npos;

	lzPath = FixPath(Path);

	//Find first file.
	f = FindFirstFileA((lzPath + "*.*").c_str(), &wfd);

	//Check for inaild path.
	if (f == INVALID_HANDLE_VALUE){
		cout << "Folder or files not found." << endl << lzPath.c_str() << endl;
		exit(1);
	}

	//Gets the list of files
	do{
		if (wfd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY){
			//Build file path
			//strcpy(lzNewPath, Path);
			//strcat(lzNewPath, wfd.cFileName);
			
			if (wfd.cFileName[0] != 46){
				NewPath = FixPath(lzPath + wfd.cFileName);

				if (AllDirs){
					if (DirExists(NewPath)){
						DirTree(NewPath, FileType, AllDirs);
					}
				}
			}

		}
		else{
			if (FileType.length() != 0){
				fExt = LCase(wfd.cFileName);
				pos = fExt.find_last_of('.');
				if (pos != string::npos){
					fExt.erase(0, pos);
					if (fExt == FileType){
						cout << lzPath.c_str() << wfd.cFileName << endl;
					}
				}
			}
			else{
				cout << lzPath.c_str() << wfd.cFileName << endl;
			}
			//Build file with full path and filename.
			//strcpy(OrgFile, lzPath);
			//strcat(OrgFile, wfd.cFileName);
			//Output filename.
			//cout << OrgFile << endl;

		}
	} while (FindNextFileA(f, &wfd) != false);

	//Close file
	FindClose(f);

}

int main(int argc, char *argv[]){
	string Temp = "";
	string fExt = "";
	string Flags = "";
	bool ScanAllDirs = false;
	int i = 2;

	int pos = string::npos;

	//Check argv
	if (argc < 2){
		
		exit(1);
	}

	//Get other args
	while (i < argc){
		Flags = LCase(argv[i]);

		if (Flags == "/s"){
			ScanAllDirs = true;
		}

		i++;
	}

	Temp = argv[1];

	pos = Temp.find('*');

	if (pos != string::npos){
		fExt = LCase(Temp.substr(pos + 1));
		if (fExt == ".*"){
			fExt = "";
		}
		//Fix the path
		Temp.erase(pos);
	}

	//Place on folder path as title.
	cout << "Folder Listing For " << Temp.c_str() << endl << endl;
	//Call DirTree procedure
	DirTree(Temp, fExt, ScanAllDirs);

	return EXIT_SUCCESS;
}